package com.clp.protocol.iec104.client.config;

import com.clp.protocol.core.pdu.nbytepdu.NBytePduClip;
import com.clp.protocol.core.common.Checkable;
import lombok.Getter;

@Getter
public class MasterControlConfig implements Checkable {
    /**
     * 默认最大重连次数
     */
    public static final int DEFAULT_MAX_RECONNECT_COUNT = 10;
    /**
     * 默认自动进行启动传输激活
     */
    public static final boolean DEFAULT_AUTO_START_DT_V = true;
    /**
     * 默认T0时间，单位为秒
     */
    public static final int DEFAULT_T0 = 6; // 30
    /**
     * 默认T1时间，单位为秒
     */
    public static final int DEFAULT_T1 = 3; // 15
    /**
     * 默认T2时间，单位为秒
     */
    public static final int DEFAULT_T2 = 2; // 10
    /**
     * 默认T3时间，单位为秒
     */
    public static final int DEFAULT_T3 = 4; // 20
    /**
     * 默认最大发送I帧数
     */
    public static final int DEFAULT_K = 12;
    /**
     * 默认最大累计确认数W
     */
    public static final int DEFAULT_W = 8;

    /***********************************************************************************************/
    private final NBytePduClip.ToStringFormat apduToStringFormat;

    private final int maxReconnectCount;
    /**
     * 是否自动进行启动传输激活
     */
    private final boolean autoStartDtV;

    /**
     * T0 T1 T2 T3 时间设置
     */
    private final int t0;
    private final int t1;
    private final int t2;
    private final int t3;
    private final int k;
    /**
     * 最大累计确认数w
     */
    private final int w;

    public static Configurer configurer() {
        return new Configurer();
    }

    private MasterControlConfig(Configurer configurer) {
        this.apduToStringFormat = configurer.apduToStringFormat;
        this.maxReconnectCount = configurer.maxReconnectCount;
        this.autoStartDtV = configurer.autoStartDtV;
        this.t0 = configurer.t0;
        this.t1 = configurer.t1;
        this.t2 = configurer.t2;
        this.t3 = configurer.t3;
        this.k = configurer.k;
        this.w = configurer.w;
    }

    @Override
    public void check() throws Throwable {
        Checker.checkT0T1T2T3(t0, t1, t2, t3);
        Checker.checkKw(k, w);
    }

    public static class Configurer {
        private NBytePduClip.ToStringFormat apduToStringFormat = NBytePduClip.ToStringFormat.DEFAULT_FORMAT;
        private int maxReconnectCount = DEFAULT_MAX_RECONNECT_COUNT;
        private boolean autoStartDtV = DEFAULT_AUTO_START_DT_V;
        /**
         * T0 T1 T2 T3 时间设置
         */
        private int t0 = DEFAULT_T0;
        private int t1 = DEFAULT_T1;
        private int t2 = DEFAULT_T2;
        private int t3 = DEFAULT_T3;
        private int k = DEFAULT_K;
        /**
         * 最大累计确认数
         */
        private int w = DEFAULT_W;

        public Configurer apduToStringFormat(NBytePduClip.ToStringFormat apduToStringFormat) {
            this.apduToStringFormat = apduToStringFormat;
            return this;
        }

        public Configurer maxReconnectCount(int maxReconnectCount) {
            this.maxReconnectCount = maxReconnectCount;
            return this;
        }

        public Configurer autoStartDtV(boolean autoStartDtV) {
            this.autoStartDtV = autoStartDtV;
            return this;
        }

        public Configurer t0t1t2t3(int t0, int t1, int t2, int t3) {
            this.t0 = t0;
            this.t1 = t1;
            this.t2 = t2;
            this.t3 = t3;
            return this;
        }

        public Configurer kw(int k, int w) {
            this.k = k;
            this.w = w;
            return this;
        }

        public MasterControlConfig configOk() {
            return new MasterControlConfig(this);
        }
    }

    public interface Checker {

        static void checkKw(int k, int w) {
            if (!(k * 2 - w * 3 >= 0)) throw new IllegalArgumentException("k=" + k + ", w=" + w + "，w的值不能超过k的三分之二");
        }

        static void checkT0T1T2T3(int t0, int t1, int t2, int t3) {
            if (!(t2 < t1 && t1 < t3)) throw new IllegalArgumentException("t1=" + t1 + ", t2=" + t2 + ", t3=" + t3 + ", t1, t2, t3 的值必须满足：t2 < t1 < t3");
        }

    }
}
